package com.dino.manager.entities;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.Model;
import org.apache.wicket.spring.injection.annot.SpringBean;

import com.dino.manager.AbstractPage;
import com.test.dao.SearchCriteria;
import com.test.dao.SearchResultSet;
import com.test.mapper.enitites.EntityModel;
import com.test.mapper.enitites.EntityProperty;
import com.test.mapper.enitites.PropertyType;
import com.test.mapper.services.EntityPropertyService;
import com.test.mapper.services.EntityService;

public class EditProperty extends AbstractPage {

	/**
	 * Generated serial version UID.
	 */
	private static final long serialVersionUID = 8234457120543792304L;

	@SpringBean
	private EntityService entityService;

	@SpringBean
	private EntityPropertyService entityPropertyService;

	private final EntityModel entity;

	private final EntityProperty property;

	public EditProperty(final Integer clientId, final String tableName) {
		entity = entityService.getEntityByTableName(clientId, tableName);
		property = initNewProperty();
		init();
	}

	public EditProperty(final EntityModel entity) {
		this.entity = entity;
		property = initNewProperty();
		init();
	}

	public EditProperty(final EntityModel entity, final EntityProperty property) {
		this.entity = entity;
		this.property = property;
		init();
	}

	public EditProperty(final Integer clientId, final String tableName, final String columnName) {
		entity = entityService.getEntityByTableName(clientId, tableName);
		property = entityPropertyService.getPropertyByColumnName(clientId, tableName, columnName);
		init();
	}

	public EditProperty(final EntityProperty prop) {
		entity = entityService.getEntityByTableName(prop.getClientId(), prop.getTableName());
		property = prop;
		init();
	}

	private EntityProperty initNewProperty() {
		final EntityProperty property = new EntityProperty();
		property.setClientId(entity.getClientId());
		property.setTableName(entity.getTableName());
		return property;
	}

	private void init() {
		add(new Label("clientId", entity.getClientId() + ""));
		add(new Label("entityName", entity.getEntityName()));
		add(new EditPropertyForm("editPropertyForm"));
	}

	private class EditPropertyForm extends Form<EntityProperty> {

		/**
		 * Generated serial version UID.
		 */
		private static final long serialVersionUID = -4555055193353387260L;

		private final TextField<String> nameField;

		private final DropDownChoice<PropertyType> typeField;

		private final TextField<Integer> lengthField;

		private final CheckBox unique;

		private final DropDownChoice<EntityModel> foreignEntityField;

		private final DropDownChoice<EntityProperty> fkColoumnField;

		public EditPropertyForm(final String id) {
			super(id);
			nameField = new TextField<String>("name", new Model<String>(property.getPropertyName() == null ? "" : property.getPropertyName()));
			add(nameField);
			typeField = new DropDownChoice<PropertyType>("type", Arrays.asList(PropertyType.values()),
					new IChoiceRenderer<PropertyType>() {

						/**
						 * Generated serial version UID.
						 */
						private static final long serialVersionUID = -2693254917716540319L;

						public Object getDisplayValue(final PropertyType object) {
							return object.name();
						}

						public String getIdValue(final PropertyType object, int index) {
							return object.getValue() + "";
						}
			});
			typeField.setModel(property.getPropertyType() == null ? new Model<PropertyType>() : new Model<PropertyType>(property.getPropertyType()));
			typeField.setRequired(true);
			typeField.add(new AjaxFormComponentUpdatingBehavior("onchange") {

				/**
				 * Generated serial version UID.
				 */
				private static final long serialVersionUID = -3527253172817745566L;

				@Override
				protected void onUpdate(final AjaxRequestTarget target) {
					final PropertyType model = typeField.getModelObject();
					updateLengthField(lengthField, model, null);
				}
			});
			add(typeField);
			lengthField = new TextField<Integer>("length", new Model<Integer>());
			updateLengthField(lengthField, property.getPropertyType(),
					property.getColumnName() == null ? null : property.getFieldLength());
			add(lengthField);
			unique = new CheckBox("unique", new Model<Boolean>(property.isUnique()));
			add(unique);
			foreignEntityField = new DropDownChoice<EntityModel>("fEntity", getEntityList(), new ChoiceRenderer<EntityModel>("entityName", "tableName"));
			foreignEntityField.setModel(property.getForeignModel() == null ? new Model<EntityModel>() : new Model<EntityModel>(property.getForeignModel()));
			foreignEntityField.add(new AjaxFormComponentUpdatingBehavior("onchange") {
				
				/**
				 * Generated serial version UID.
				 */
				private static final long serialVersionUID = -3527253172817745566L;

				@Override
				protected void onUpdate(final AjaxRequestTarget target) {
					final EntityModel model = foreignEntityField.getModelObject();
					if (model == null) {
						fkColoumnField.setChoices(new ArrayList<EntityProperty>());
						fkColoumnField.setEnabled(false);
					} else {
						fkColoumnField.setEnabled(true);
						fkColoumnField.setChoices(getAvailableColumns(model));
					}
					target.add(fkColoumnField);
				}
			});
			add(foreignEntityField);
			fkColoumnField = new DropDownChoice<EntityProperty>("fkColumn", new Model<EntityProperty>(),
					new ArrayList<EntityProperty>(), new ChoiceRenderer<EntityProperty>("propertyName", "columnName"));
			fkColoumnField.setOutputMarkupId(true);
			if (property.getForeignKeyTo() != null) {				
				fkColoumnField.setEnabled(true);
				fkColoumnField.setChoices(getAvailableColumns(property.getForeignModel()));
			} else {
				fkColoumnField.setEnabled(false);
			}
			add(fkColoumnField);
		}
		
		private void updateLengthField(final TextField<Integer> lengthField, final PropertyType type,
				final Integer defVal)
		{
			switch (type) {
			case DATE:
				lengthField.setEnabled(false);
				lengthField.setModelObject(8);
				break;
			case ENTITY: 
				lengthField.setEnabled(false);
				lengthField.setModelObject(80);
				break;
			case TEXT:
				lengthField.setEnabled(true);
				lengthField.setModelObject(defVal == null ? 80 : defVal);
				break;
			case NUMBER:
				lengthField.setEnabled(true);
				lengthField.setModelObject(defVal == null ? 4 : defVal);
				break;
			default:
				lengthField.setEnabled(false);
				lengthField.setModelObject(0);
			}
		}

		private List<EntityModel> getEntityList() {
			final SearchCriteria criteria = new SearchCriteria();
			criteria.addPropertyCriteria("clientId", entity.getClientId());
			final SearchResultSet<EntityModel> rs = entityService.searchForEntities(criteria);
			return new ArrayList<EntityModel>(rs.getResultList());
		}

		private List<EntityProperty> getAvailableColumns(final EntityModel model) {
			final SearchCriteria criteria = new SearchCriteria();
			criteria.addPropertyCriteria("clientId", entity.getClientId());
			criteria.addPropertyCriteria("tableName", model.getTableName());
			criteria.addPropertyCriteria("unique", Boolean.TRUE);
			return new ArrayList<EntityProperty>(entityPropertyService.searchForProperties(criteria).getResultList());
		}

	}
}
